home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / mypal.zip / MYPAL.C < prev    next >
C/C++ Source or Header  |  1993-02-17  |  18KB  |  558 lines

  1. /***************************************************************************
  2.  *                                       *
  3.  *  PROGRAM    : MyPal.c                           *
  4.  *                                       *
  5.  *  PURPOSE    : Sets up a bar representation of the current physical       *
  6.  *          palette and displays useful information regarding       *
  7.  *          pixel colors and palette indices.               *
  8.  *                                       *
  9.  *  FUNCTIONS    : WinMain() - calls initialization function,           *
  10.  *                  processes message loop               *
  11.  *                                       *
  12.  *          WndProc() - Window function for app. Processes       *
  13.  *                  window messages.                   *
  14.  *                                       *
  15.  *        ShowColor() - Displays a little box on each side of the    *
  16.  *                  caption bar displaying the pixel color at the*
  17.  *                  mouse position.                   *
  18.  ***************************************************************************/
  19.  
  20. #include <windows.h>
  21. #include "mypal.h"
  22.  
  23. HANDLE        hPal;           /* Handle to the application's logical palette */
  24. HANDLE          hPal2;          /* Handle to the application's logical palette */
  25. static INT    nSizeX;        /* Width of the application window          */
  26. static INT    nSizeY;        /* Height of the application window          */
  27. NPLOGPALETTE    pLogPal;       /* Pointer to program's logical palette        */
  28. NPLOGPALETTE    pLogPal2;       /* Pointer to program's logical palette        */
  29. INT        nXBorder;      /* Width of window border              */
  30. INT        nXTitle;       /* Width of title bar                  */
  31. INT        nYTitle;       /* Height of title bar                  */
  32. BOOL        bCaptureOn;    /* Indicates if mouse capture is on          */
  33. INT        iIndex;        /* Last index selected in palette          */
  34. CHAR        szTitlebuf[90];/* Buffer for pixel and palette info. text     */
  35. HDC        hDCGlobal;     /* The Screen DC                   */
  36. INT        iNumColors;    /* Number of colors supported by device          */
  37. INT        iRasterCaps;   /* Raster capabilities                  */
  38. RECT        rClientRect;   /* Client rectangle coordinates              */
  39. DWORD     dwPal[PALETTESIZE];   /* Stores palette entries for later lookup     */
  40. INT        iGlobalXOffset;
  41. INT        iGlobalYOffset;
  42. INT        iYMiddle;
  43.  
  44. LONG APIENTRY WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam);
  45.  
  46. /****************************************************************************
  47.  *                                        *
  48.  *  FUNCTION   : void ShowColor(HWND hWnd, HDC hDC)                *
  49.  *                                        *
  50.  *  PURPOSE    : Displays a little box on each side of the caption bar        *
  51.  *         displaying the pixel color at the mouse position.        *
  52.  *                                        *
  53.  ****************************************************************************/
  54. VOID ShowColor (
  55.     HWND  hWnd,
  56.     HDC   hDC)
  57. {
  58.      HBRUSH  hBrush, hOldBrush;
  59.  
  60.      hBrush    = CreateSolidBrush ( PALETTEINDEX(iIndex) );
  61.      hOldBrush = SelectObject (hDC,hBrush) ;
  62.  
  63.      GetWindowRect (hWnd, (LPRECT)&rClientRect);
  64.  
  65.      PatBlt ( hDC,
  66.           rClientRect.left + nXTitle + nXBorder + 1,
  67.           rClientRect.top + nXBorder,
  68.           nXTitle,
  69.           nYTitle,
  70.           PATCOPY);
  71.  
  72.      PatBlt(hDC,
  73.         rClientRect.right - ( 3 * nXTitle + nXBorder + 2),
  74.         rClientRect.top + nXBorder,
  75.         nXTitle,
  76.         nYTitle,
  77.         PATCOPY);
  78.      SelectObject (hDC, hOldBrush);
  79.      DeleteObject (hBrush) ;
  80. }
  81.  
  82. /****************************************************************************
  83.  *                                        *
  84.  *  FUNCTION   : WinMain(HANDLE, HANDLE, LPSTR, int)                *
  85.  *                                        *
  86.  *  PURPOSE    : Creates the app. window and processes the message loop.    *
  87.  *                                        *
  88.  ****************************************************************************/
  89. int APIENTRY WinMain(
  90.     HANDLE hInstance,
  91.     HANDLE hPrevInstance,
  92.     LPSTR lpCmdLine,
  93.     int nCmdShow
  94.     )
  95. {
  96.      static CHAR szAppName [] = "MyPal";
  97.      HWND     hWnd;
  98.      WNDCLASS     wndclass;
  99.      MSG     msg ;
  100.      INT     xScreen;
  101.      INT     yScreen;
  102.  
  103.      UNREFERENCED_PARAMETER( lpCmdLine );
  104.  
  105.      if (!hPrevInstance){
  106.      wndclass.style     = CS_HREDRAW | CS_VREDRAW;
  107.      wndclass.lpfnWndProc    = (WNDPROC) WndProc;
  108.      wndclass.cbClsExtra    = 0;
  109.      wndclass.cbWndExtra    = 0;
  110.      wndclass.hInstance    = hInstance;
  111.      wndclass.hIcon     = LoadIcon(hInstance, szAppName);
  112.      wndclass.hCursor    = LoadCursor (NULL, IDC_ARROW);
  113.      wndclass.hbrBackground = GetStockObject (BLACK_BRUSH);
  114.      wndclass.lpszMenuName    = szAppName;
  115.      wndclass.lpszClassName = szAppName;
  116.  
  117.      if (!RegisterClass (&wndclass))
  118.          return FALSE ;
  119.      }
  120.  
  121.      /* Do some global initializations */
  122.      xScreen     = GetSystemMetrics (SM_CXSCREEN);
  123.      yScreen     = GetSystemMetrics (SM_CYSCREEN);
  124.      nXBorder     = (INT)GetSystemMetrics (SM_CXFRAME);
  125.      nXTitle     = (INT)GetSystemMetrics (SM_CXSIZE);
  126.      nYTitle     = (INT)GetSystemMetrics (SM_CYSIZE);
  127.      iIndex     = 0;
  128.      bCaptureOn  = FALSE;
  129.  
  130.      hDCGlobal     = GetDC (NULL);
  131.      iRasterCaps = GetDeviceCaps(hDCGlobal, RASTERCAPS);
  132.      iRasterCaps = (iRasterCaps & RC_PALETTE) ? TRUE : FALSE;
  133.  
  134.      if (iRasterCaps)
  135.      iNumColors = GetDeviceCaps(hDCGlobal, SIZEPALETTE);
  136.      else
  137.      iNumColors = GetDeviceCaps( hDCGlobal, NUMCOLORS);
  138.      ReleaseDC (NULL,hDCGlobal);
  139.  
  140.      nSizeX = ((xScreen - 2*nXBorder) / PALETTESIZE) * PALETTESIZE;
  141.  
  142.      /* create the app. window */
  143.      hWnd = CreateWindow (szAppName,
  144.               "My Physical Palette ",
  145.               WS_OVERLAPPEDWINDOW,
  146.               (xScreen-nSizeX) / 2 - nXBorder,
  147.               yScreen - ( 4 * GetSystemMetrics (SM_CYCAPTION)),
  148.               nSizeX + 2 * nXBorder,
  149.               4 * GetSystemMetrics (SM_CYCAPTION),
  150.               NULL,
  151.               NULL,
  152.               hInstance,
  153.               NULL);
  154.      ShowWindow (hWnd, nCmdShow);
  155.      UpdateWindow (hWnd);
  156.  
  157.      while (GetMessage (&msg, NULL, 0, 0)){
  158.        TranslateMessage (&msg) ;
  159.        DispatchMessage (&msg) ;
  160.      }
  161.  
  162.      return msg.wParam ;
  163. }
  164.  
  165. /******************************************************************************
  166.  *                                          *
  167.  *  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)                  *
  168.  *                                          *
  169.  *  PURPOSE:  Processes window messages and sets up a 256 bar representation  *
  170.  *          of the current physical palette. Specifically, in response to:  *
  171.  *                                          *
  172.  *         WM_CREATE  -Allocates for and sets up a LOGPALETTE          *
  173.  *                 structure, creates a logical palette the same    *
  174.  *                 size as the physical palette and obtains a       *
  175.  *                 handle to the logical palette.              *
  176.  *                                          *
  177.  *         WM_DESTROY -Destroys the logical palette and shuts down app. *
  178.  *                                          *
  179.  *         WM_PAINT   -Resizes client area to hold as many vertical     *
  180.  *                 color bars as there are physical palette entries.*
  181.  *                 Also realises the current logical palette and    *
  182.  *                 draws one color bar corresponding to each          *
  183.  *                 palette entry                      *
  184.  *                                          *
  185.  *         WM_RBUTTONDOWN -Captures the mouse and initiates the below       *
  186.  *                 process:                          *
  187.  *                                          *
  188.  *         WM_MOUSEMOVE   -Following a WM_RBUTTONDOWN, if the right mouse   *
  189.  *                 key is depressed, displays info about the          *
  190.  *                 pixel RGB value and palette index of the mouse   *
  191.  *                 coordinates.                      *
  192.  *                                          *
  193.  *         WM_RBUTTONUP   -Release mouse capture and terminates the above   *
  194.  *                 process                          *
  195.  *                                          *
  196.  *         WM_LBUTTONDOWN -Determines and displays the palette index and    *
  197.  *                 RGB value of the bar under the mouse.          *
  198.  *                                          *
  199.  *         WM_KEYDOWN     -Allows use of the arrow keys in stepping thro'   *
  200.  *                 palette entries.                      *
  201.  *                                          *
  202.  *****************************************************************************/
  203. LONG APIENTRY WndProc (
  204.     HWND     hWnd,
  205.     UINT     iMessage,
  206.     UINT     wParam,
  207.     LONG     lParam)
  208. {
  209.     HDC       hDC;
  210.     PAINTSTRUCT   ps;
  211.     INT              iLoop;
  212.     INT       nStart;
  213.     HBRUSH      hBrush;
  214.     HBRUSH      hOldBrush;
  215.  
  216.     MPOINT      pt;
  217.     static INT    nIncr;
  218.     static DWORD  dwColor;
  219.     static DWORD  dwLastColor;
  220.     static INT      i, x;
  221.  
  222.     switch (iMessage) {
  223.      case WM_DESTROY:
  224.           /* delete the handle to the logical palette if it has any
  225.            * color entries and quit.
  226.            */
  227.           if (pLogPal->palNumEntries) {
  228.           DeleteObject (hPal);
  229.                   DeleteObject (hPal2);
  230.               }
  231.           PostQuitMessage (0) ;
  232.           break ;
  233.  
  234.      case WM_CREATE:
  235.           /* Allocate enough memory for a logical palette with
  236.            * PALETTESIZE entries and set the size and version fields
  237.            * of the logical palette structure.
  238.            */
  239.           pLogPal = (NPLOGPALETTE) LocalAlloc (LMEM_FIXED,
  240.                           (sizeof (LOGPALETTE) +
  241.                           (sizeof (PALETTEENTRY) * (PALETTESIZE))));
  242.  
  243.           if(!pLogPal){
  244.             MessageBox(hWnd, "<WM_CREATE> Not enough memory for palette.", NULL, MB_OK | MB_ICONHAND);
  245.             PostQuitMessage (0) ;
  246.             break;
  247.           }
  248.  
  249.           pLogPal2 = (NPLOGPALETTE) LocalAlloc (LMEM_FIXED,
  250.                           (sizeof (LOGPALETTE) +
  251.                           (sizeof (PALETTEENTRY) * (PALETTESIZE))));
  252.  
  253.  
  254.           if(!pLogPal2){
  255.             MessageBox(hWnd, "<WM_CREATE> Not enough memory for palette.", NULL, MB_OK | MB_ICONHAND);
  256.             PostQuitMessage (0) ;
  257.             break;
  258.           }
  259.  
  260.           pLogPal->palVersion    = 0x300;
  261.           pLogPal->palNumEntries = PALETTESIZE;
  262.  
  263.           /* fill in intensities for all palette entry colors */
  264.           for (iLoop = 0; iLoop < PALETTESIZE; iLoop++) {
  265.           *((WORD *) (&pLogPal->palPalEntry[iLoop].peBlue)) = (WORD)iLoop;
  266.                   pLogPal->palPalEntry[iLoop].peGreen  = 0;
  267.           pLogPal->palPalEntry[iLoop].peRed  = 0;
  268.           pLogPal->palPalEntry[iLoop].peFlags = PC_NOCOLLAPSE;
  269.           }
  270.           pLogPal2->palVersion    = 0x300;
  271.           pLogPal2->palNumEntries = PALETTESIZE;
  272.  
  273.               /* fill in intensities for all palette entry colors */
  274.           for (iLoop = 0; iLoop < 127; iLoop++) {
  275.           *((WORD *) (&pLogPal2->palPalEntry[iLoop].peBlue)) = (WORD)iLoop;
  276.                   pLogPal2->palPalEntry[iLoop].peGreen  = 0;
  277.           pLogPal2->palPalEntry[iLoop].peRed  = 0;
  278.           pLogPal2->palPalEntry[iLoop].peFlags = PC_RESERVED;
  279.           }
  280.  
  281.           for (iLoop = 128; iLoop < PALETTESIZE; iLoop++) {
  282.           *((WORD *) (&pLogPal2->palPalEntry[iLoop].peRed)) = (WORD)(PALETTESIZE-iLoop);
  283.                   *((WORD *) (&pLogPal2->palPalEntry[iLoop].peGreen)) = (WORD)(PALETTESIZE-iLoop);
  284.           pLogPal2->palPalEntry[iLoop].peBlue  = 0;
  285.           pLogPal2->palPalEntry[iLoop].peFlags = PC_RESERVED;
  286.           }
  287.           /*  create a logical color palette according the information
  288.            *  in the LOGPALETTE structure.
  289.            */
  290.           hPal = CreatePalette ((LPLOGPALETTE) pLogPal) ;
  291.               hPal2 = CreatePalette ((LPLOGPALETTE) pLogPal2) ;
  292.           break;
  293.  
  294.      case WM_GETMINMAXINFO:
  295.  
  296.           ((LPRGPT)lParam)->iInfo[6] = nXBorder * 2 + PALETTESIZE;
  297.           ((LPRGPT)lParam)->iInfo[7] = nXBorder * 2 + nYTitle*3;
  298.  
  299.           return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
  300.           break;
  301.  
  302.      case WM_PAINT: {
  303.          static BOOL bToggle=TRUE;
  304.  
  305.           /* Divide client width into equal-sized parts, one per palette
  306.            * entry, and re-calculate client width so that it will display
  307.            * exactly as many vertical bars as there are palette entries.
  308.            */
  309.            GetClientRect(hWnd,(LPRECT) &rClientRect);
  310.            nSizeX = (rClientRect.right - rClientRect.left);
  311.            nSizeX = (nSizeX/iNumColors) * iNumColors;
  312.  
  313.            nSizeY = rClientRect.bottom - rClientRect.top;
  314.            GetWindowRect(hWnd,(LPRECT) &rClientRect);
  315.  
  316.           /* Adjust window width so that it can display exactly
  317.            * as many vertical bars( of equal width) as there are palette
  318.            * colors.
  319.            */
  320.  
  321.           SetWindowPos( hWnd,
  322.                 (HWND)NULL,
  323.                 0,
  324.                 0,
  325.                 nSizeX + 2*nXBorder,
  326.                 rClientRect.bottom - rClientRect.top,
  327.                 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  328.  
  329.           hDC = BeginPaint(hWnd, &ps);
  330.  
  331.           /* Select the palette into the window device context and
  332.            * make the Palette Manager map the logical palette to the
  333.            * system palette (realize it).
  334.            */
  335.               //SetSystemPaletteUse(hDC, SYSPAL_NOSTATIC);
  336.  
  337.           SelectPalette (hDC, (bToggle ? hPal : hPal2), FALSE);
  338.           RealizePalette (hDC);
  339.  
  340.  
  341.           /* Calculate width of each color bar to be displayed */
  342.           nIncr = nSizeX / iNumColors;
  343.  
  344.           /* Paint the individual bars separately on the app. window */
  345.           for (nStart = iLoop = 0; iLoop < iNumColors; iLoop++){
  346.  
  347.           /* Since this app. uses a logical palette, use the
  348.            * PALETTEINDEX macro to specify the palette entry
  349.            * index instead of using an explicit RGB value.
  350.            */
  351.           hBrush       = CreateSolidBrush (PALETTEINDEX (iLoop));
  352.           dwPal[iLoop] = GetNearestColor (hDC, PALETTEINDEX (iLoop) );
  353.           hOldBrush    = SelectObject (hDC,hBrush) ;
  354.           PatBlt (hDC, nStart, 0, nIncr, nSizeY, PATCOPY);
  355.           nStart       += nIncr;
  356.           SelectObject (hDC, hOldBrush);
  357.           DeleteObject (hBrush) ;
  358.           }
  359.           wsprintf (szTitlebuf, "MyPal Colors= %d", iNumColors);
  360.           SetWindowText (hWnd, (LPSTR)szTitlebuf);
  361.  
  362.           EndPaint(hWnd,&ps);
  363.  
  364.               bToggle = (bToggle ? FALSE : TRUE);
  365.           break ;
  366.  
  367.          }
  368.      case WM_MOUSEMOVE:
  369.  
  370.           if (wParam & MK_RBUTTON) {
  371.  
  372.           POINT pt;
  373.                   
  374. #ifdef WIN16
  375.           /* Convert mouse position to screen coordinates */
  376.           pt.x = LOWORD(lParam);
  377.           pt.y = HIWORD(lParam);
  378. #else
  379.           LONG2POINT(lParam, pt);    
  380. #endif
  381.           ClientToScreen(hWnd, &pt);
  382.  
  383.           /* Get RGB value (color) of pixel under mouse coordinate */
  384.           dwColor = GetPixel(hDCGlobal, pt.x, pt.y);
  385.  
  386.           /* If color value already exists in palette lookup table,
  387.            * obtain it's index.
  388.            */
  389.           for (i=0 ; i < iNumColors ; i++)
  390.               if ( dwColor == dwPal[i] )
  391.               break;
  392.           iIndex = i;
  393.  
  394.           /* If previous color value was not identical to current one,
  395.            * display color boxes on either side of title bar,
  396.            * the R, G, B values and palette index of current color.
  397.            */
  398.           if (dwColor != dwLastColor) {
  399.               wsprintf ( szTitlebuf,
  400.                  "MyPal Colors=%d  Index=%d  R=%3u G=%3u B=%3u",
  401.                  iNumColors,
  402.                  iIndex,
  403.                  (WORD)(BYTE) GetRValue (dwColor),
  404.                  (WORD)(BYTE) GetGValue (dwColor),
  405.                  (WORD)(BYTE) GetBValue (dwColor));
  406.               SetWindowText (hWnd, (LPSTR)szTitlebuf);
  407.               ShowColor (hWnd, hDCGlobal);
  408.               dwLastColor = dwColor;
  409.           }
  410.           }
  411.           break;
  412.  
  413.      case WM_RBUTTONDOWN:
  414.  
  415.           /* Determine number of color bar under mouse, thus the index
  416.            * of color in palette.
  417.            */
  418.           x = LOWORD(lParam);
  419.           iIndex = (x / nIncr );
  420.  
  421.           wsprintf ( szTitlebuf,
  422.              "MyPal Colors=%d  Index=%d  PalSize=%d RasterCaps:%d",
  423.              iNumColors,
  424.              iIndex,
  425.              iNumColors,
  426.              iRasterCaps );
  427.  
  428.           SetWindowText (hWnd, (LPSTR)szTitlebuf);
  429.  
  430.           /* Set mouse capture so that subsequent WM_MOUSEMOVEs
  431.            * (with right mouse button depressed) will allow MyPal
  432.            * to display RGB info anywhere on the screen without losing
  433.            * the focus.
  434.            */
  435.           SetCapture (hWnd);
  436.           bCaptureOn = TRUE;
  437.           hDCGlobal = GetDC(NULL);
  438.           if (hPal) {
  439.           SelectPalette (hDCGlobal, hPal, FALSE);
  440.           RealizePalette (hDCGlobal);
  441.           }
  442.           break;
  443.  
  444.      case WM_RBUTTONUP:
  445.           /* Stops displaying RGB and palette info and releases mouse
  446.            * capture
  447.            */
  448.           ReleaseDC (NULL, hDCGlobal);
  449.           bCaptureOn = FALSE;
  450.           ReleaseCapture ();
  451.           break;
  452.  
  453.      case WM_MOVE:
  454.           /* If you have a wide column, this adds 1/2 so X is centered */
  455.           iGlobalXOffset  = LOWORD (lParam);
  456.           iGlobalYOffset  = HIWORD (lParam) + nXBorder;
  457.           break;
  458.  
  459.      case WM_SIZE:
  460.           iYMiddle = (HIWORD (lParam)/2);
  461.           break;
  462.  
  463.      case WM_LBUTTONDOWN:
  464.      case WM_KEYDOWN:
  465.  
  466.          if (iMessage == WM_LBUTTONDOWN){
  467.          /* determine which column was hit by the mouse */
  468.          x = LOWORD(lParam);
  469.          iIndex = (x / nIncr );
  470.          }
  471.          else{
  472.          /* Use arrow keys to step thro' the palette entries */
  473.          switch (wParam) {
  474.              case VK_RIGHT:
  475.              case VK_UP:
  476.                   /* go to next (higher) palette entry */
  477.                   iIndex++;
  478.                   break;
  479.              case VK_LEFT:
  480.              case VK_DOWN:
  481.                   /* go to previous (lower) palette entry */
  482.                   iIndex--;
  483.                   break;
  484.              case VK_NEXT:
  485.                   iIndex += 10;
  486.                   break;
  487.              case VK_PRIOR:
  488.                   iIndex -= 10;
  489.                   break;
  490.              case VK_HOME:
  491.                   /* go to first palette entry */
  492.                   iIndex = 0;
  493.                   break;
  494.              case VK_END:
  495.                   /* go to last palette entry */
  496.                   iIndex = iNumColors-1;
  497.                   break;
  498.              default:
  499.                   return 0L;
  500.                   break;
  501.          }
  502.          /* Make sure the palette index is within range else
  503.           * set it to the limiting values and give a warning beep.
  504.           */
  505.          if (iIndex < 0) {
  506.              iIndex = 0;
  507.              MessageBeep(1);
  508.          }
  509.          else{
  510.              if (iIndex > iNumColors-1) {
  511.              iIndex = iNumColors-1;
  512.              MessageBeep(1);
  513.               }
  514.          }
  515.  
  516.          pt.x = (SHORT)((iIndex * nIncr) +
  517.             iGlobalXOffset     +
  518.             ((nIncr > 1) ? (nIncr / 2) : 1));
  519.          pt.y = (SHORT)(iYMiddle + iGlobalYOffset);
  520.  
  521.          SetCursorPos (pt.x, pt.y);
  522.          }
  523.  
  524.          if (TRUE == bCaptureOn) {
  525.          MessageBeep(1);
  526.          break;
  527.          }
  528.  
  529.          /* Select & realize the palette or the colors > 0x7
  530.           * will not match up.
  531.           */
  532.          hDC = GetDC(NULL);
  533.          SelectPalette  (hDC, hPal, 1);
  534.          RealizePalette (hDC) ;
  535.  
  536.          dwColor = GetNearestColor (hDC, PALETTEINDEX (iIndex));
  537.  
  538.          wsprintf ( szTitlebuf,
  539.             "MyPal Colors=%d  Index=%d  R=%3u G=%3u B=%3u",
  540.             iNumColors,
  541.             iIndex,
  542.             (WORD)(BYTE)GetRValue (dwColor),
  543.             (WORD)(BYTE)GetGValue (dwColor),
  544.             (WORD)(BYTE)GetBValue (dwColor)
  545.              );
  546.  
  547.          SetWindowText (hWnd, (LPSTR)szTitlebuf);
  548.          ShowColor (hWnd,hDC);
  549.          ReleaseDC(NULL, hDC);
  550.          break;
  551.  
  552.      default:
  553.           return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
  554.  
  555.     }
  556.     return 0L ;
  557. }
  558.